/**
 * libp2p集群验证脚本
 * 
 * 这个脚本启动多个节点来验证libp2p集群的功能:
 * 1. 节点发现和成员管理
 * 2. 领导者选举
 * 3. Actor跨节点通信
 * 4. 故障转移
 */

import { Actor } from '../src/actor/actor';
import { PID } from '../src/actor/pid';
import { ActorSystem } from '../src/actor/actorSystem';
import { Props } from '../src/actor/props';
import { Context } from '../src/actor/context';
import { Remote } from '../src/remote/remote';
import { Cluster, ClusterEventType, ClusterEvent } from '../src/cluster/cluster';
import { ClusterConfig } from '../src/cluster/clusterConfig';
import { Libp2pProvider } from '../src/cluster/providers/libp2pProvider';
import { LocalIdentityLookup } from '../src/cluster/providers/localIdentityLookup';
import { GrainBase, GrainRegistry } from '../src/cluster/grain';
import { ClusterIdentity } from '../src/cluster/clusterIdentity';
import { ProcessRegistry } from '../src/actor/processRegistry';
import { ClusterRouter } from '../src/cluster/clusterRouter';

// 延时函数
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

// ====== 定义测试Actor ======

// 测试Actor消息类型
type TestActorMessage = 
  | { type: 'ping' }
  | { type: 'get-state' }
  | { type: 'update-state', value: string };

// 测试Actor
class TestActor implements Actor {
  private state: string = '';
  private receivedPings: number = 0;
  
  constructor(private id: string) {
    console.log(`[TestActor:${this.id}] 创建`);
  }
  
  async receive(context: Context): Promise<void> {
    try {
      // 获取实际的消息对象
      const message = context.message();
      console.log(`[TestActor:${this.id}] 收到消息:`, typeof message, message);
      
      // 获取发送者（如果有）
      const sender = context.sender();
      console.log(`[TestActor:${this.id}] 发送者:`, sender?.toString() || '无发送者');
      
      // 检查是否为对象消息
      if (message && typeof message === 'object') {
        // 如果消息有type字段，按类型处理
        if ('type' in message) {
          const msgType = message.type;
          console.log(`[TestActor:${this.id}] 处理类型为 '${msgType}' 的消息`);
          
          switch (msgType) {
            case 'ping': {
              console.log(`[TestActor:${this.id}] 处理ping消息`);
              this.receivedPings++;
              
              // 构建响应
              const response = { 
                success: true, 
                pings: this.receivedPings, 
                nodeId: this.id,
                timestamp: Date.now()
              };
              
              // 如果有发送者，发送响应
              if (sender) {
                console.log(`[TestActor:${this.id}] 发送ping响应给 ${sender.toString()}:`, response);
                
                // 使用context.respond方法
                try {
                  context.respond(response);
                  console.log(`[TestActor:${this.id}] ping响应发送成功`);
                } catch (error) {
                  console.error(`[TestActor:${this.id}] 发送ping响应失败:`, error);
                  // 替代方案：直接向发送者发送消息
                  console.log(`[TestActor:${this.id}] 尝试使用直接发送替代方案`);
                  context.actorSystem().root.send(sender, response);
                }
              } else {
                console.warn(`[TestActor:${this.id}] 无法响应ping: 没有发送者`);
              }
              
              break;
            }
            
            case 'get-state': {
              console.log(`[TestActor:${this.id}] 处理get-state消息`);
              
              // 构建响应
              const response = { 
                state: this.state, 
                pings: this.receivedPings, 
                nodeId: this.id,
                timestamp: Date.now()
              };
              
              // 如果有发送者，发送响应
              if (sender) {
                console.log(`[TestActor:${this.id}] 发送state响应给 ${sender.toString()}:`, response);
                
                // 使用context.respond方法
                try {
                  context.respond(response);
                  console.log(`[TestActor:${this.id}] state响应发送成功`);
                } catch (error) {
                  console.error(`[TestActor:${this.id}] 发送state响应失败:`, error);
                  // 替代方案：直接向发送者发送消息
                  console.log(`[TestActor:${this.id}] 尝试使用直接发送替代方案`);
                  context.actorSystem().root.send(sender, response);
                }
              } else {
                console.warn(`[TestActor:${this.id}] 无法响应get-state: 没有发送者`);
              }
              
              break;
            }
            
            case 'update-state': {
              console.log(`[TestActor:${this.id}] 处理update-state消息`);
              
              // 更新状态
              if ('value' in message && typeof message.value === 'string') {
                console.log(`[TestActor:${this.id}] 更新状态: ${this.state} -> ${message.value}`);
                this.state = message.value;
                
                // 构建响应
                const response = { 
                  success: true, 
                  state: this.state, 
                  nodeId: this.id,
                  timestamp: Date.now()
                };
                
                // 如果有发送者，发送响应
                if (sender) {
                  console.log(`[TestActor:${this.id}] 发送update响应给 ${sender.toString()}:`, response);
                  
                  // 使用context.respond方法
                  try {
                    context.respond(response);
                    console.log(`[TestActor:${this.id}] update响应发送成功`);
                  } catch (error) {
                    console.error(`[TestActor:${this.id}] 发送update响应失败:`, error);
                    // 替代方案：直接向发送者发送消息
                    console.log(`[TestActor:${this.id}] 尝试使用直接发送替代方案`);
                    context.actorSystem().root.send(sender, response);
                  }
                } else {
                  console.warn(`[TestActor:${this.id}] 无法响应update-state: 没有发送者`);
                }
              } else {
                console.warn(`[TestActor:${this.id}] update-state消息中无value字段或类型非字符串`);
                
                // 发送错误响应
                if (sender) {
                  const errorResponse = {
                    error: 'Invalid update-state message: missing or invalid value field',
                    nodeId: this.id,
                    timestamp: Date.now()
                  };
                  
                  try {
                    context.respond(errorResponse);
                  } catch (error) {
                    console.error(`[TestActor:${this.id}] 发送错误响应失败:`, error);
                    context.actorSystem().root.send(sender, errorResponse);
                  }
                }
              }
              
              break;
            }
            
            default: {
              console.warn(`[TestActor:${this.id}] 收到未知消息类型: ${msgType}`);
              
              // 发送错误响应
              if (sender) {
                const errorResponse = {
                  error: `Unknown message type: ${msgType}`,
                  nodeId: this.id,
                  timestamp: Date.now()
                };
                
                try {
                  context.respond(errorResponse);
                } catch (error) {
                  console.error(`[TestActor:${this.id}] 发送错误响应失败:`, error);
                  context.actorSystem().root.send(sender, errorResponse);
                }
              }
              
              break;
            }
          }
        } else {
          console.warn(`[TestActor:${this.id}] 消息没有type字段:`, message);
          
          // 尝试猜测消息类型
          if ('ping' in message) {
            console.log(`[TestActor:${this.id}] 猜测为ping消息`);
            this.receivedPings++;
            
            if (sender) {
              const response = {
                success: true,
                pings: this.receivedPings,
                nodeId: this.id,
                timestamp: Date.now()
              };
              
              try {
                context.respond(response);
              } catch (error) {
                console.error(`[TestActor:${this.id}] 发送猜测ping响应失败:`, error);
                context.actorSystem().root.send(sender, response);
              }
            }
          } else {
            // 发送错误响应
            if (sender) {
              const errorResponse = {
                error: 'Message has no type field',
                nodeId: this.id,
                timestamp: Date.now()
              };
              
              try {
                context.respond(errorResponse);
              } catch (error) {
                console.error(`[TestActor:${this.id}] 发送错误响应失败:`, error);
                context.actorSystem().root.send(sender, errorResponse);
              }
            }
          }
        }
      } else {
        console.warn(`[TestActor:${this.id}] 收到非对象消息:`, message);
        
        // 发送错误响应
        if (sender) {
          const errorResponse = {
            error: 'Message is not an object',
            nodeId: this.id,
            timestamp: Date.now()
          };
          
          try {
            context.respond(errorResponse);
          } catch (error) {
            console.error(`[TestActor:${this.id}] 发送错误响应失败:`, error);
            context.actorSystem().root.send(sender, errorResponse);
          }
        }
      }
    } catch (error: any) {
      console.error(`[TestActor:${this.id}] 处理消息时发生错误:`, error);
      
      // 发送错误响应
      const sender = context.sender();
      if (sender) {
        const errorResponse = {
          error: `Internal error: ${error.message || 'Unknown error'}`,
          nodeId: this.id,
          timestamp: Date.now()
        };
        
        try {
          context.respond(errorResponse);
        } catch (respondError) {
          console.error(`[TestActor:${this.id}] 发送错误响应失败:`, respondError);
          try {
            context.actorSystem().root.send(sender, errorResponse);
          } catch (sendError) {
            console.error(`[TestActor:${this.id}] 发送错误响应彻底失败:`, sendError);
          }
        }
      }
    }
  }
}

// ====== 定义测试Grain ======

interface ITestGrain {
  ping(): Promise<{ success: boolean; pings: number; nodeId: string }>;
  getState(): Promise<{ state: string; pings: number; nodeId: string }>;
  updateState(value: string): Promise<{ success: boolean; state: string; nodeId: string }>;
}

class TestGrain extends GrainBase implements ITestGrain {
  protected pid: PID | null = null;

  constructor(cluster: Cluster, grainId: string) {
    super(cluster, 'test', grainId);
    console.log(`[TestGrain] 创建TestGrain: kind=test, id=${grainId}`);
  }

  private async getOrActivateActor(): Promise<PID> {
    try {
      if (this.pid) {
        // 如果已有PID，尝试验证是否有效
        console.log(`检查现有PID: ${this.pid.toString()}`);
        
        // 验证PID是否仍然有效
        const registry = ProcessRegistry.getInstance();
        if (registry.resolveProcess && this.pid.id) {
          const foundProcess = registry.resolveProcess(this.pid.id);
          if (foundProcess) {
            return this.pid;
          }
        } else if (registry.get) {
          const foundProcess = registry.get(this.pid);
          if (foundProcess) {
            return this.pid;
          }
        }
        
        console.log(`PID无效，需要重新激活: ${this.pid.toString()}`);
      }
      
      // 通过集群获取激活的Grain
      console.log(`激活Grain: ${this.kind}/${this.identity}`);
      const identity = new ClusterIdentity(this.kind, this.identity);
      
      // 确保集群有 getAsync 方法
      if (!this.cluster.getAsync) {
        throw new Error(`Cluster 实例没有 getAsync 方法`);
      }
      
      // 使用getAsync激活
      const pid = await this.cluster.getAsync(this.kind, this.identity);
      if (!pid) {
        throw new Error(`无法激活Grain: ${this.kind}/${this.identity}`);
      }
      
      this.pid = pid;
      console.log(`Grain已激活: ${pid.toString()}`);
      
      return pid;
    } catch (error) {
      console.error(`激活Grain失败:`, error);
      throw error;
    }
  }
  
  async ping(): Promise<{ success: boolean; pings: number; nodeId: string }> {
    try {
      // 确保调用前已经获取了有效的 Actor PID
      if (!this.pid) {
        if (!this.cluster.getAsync) {
          throw new Error('Cluster 实例没有 getAsync 方法');
        }
        
        const pid = await this.cluster.getAsync(this.kind, this.identity);
        if (!pid) {
          throw new Error(`无法激活 TestGrain: ${this.kind}/${this.identity}`);
        }
        
        this.pid = pid;
      }
      
      // 发送消息并等待响应
      const response = await this.requestToActor<{ success: boolean; pings: number; nodeId: string }>({ type: 'ping' });
      return response;
    } catch (error) {
      console.error(`[TestGrain] Ping 失败:`, error);
      throw error;
    }
  }
  
  async getState(): Promise<{ state: string; pings: number; nodeId: string }> {
    try {
      // 确保调用前已经获取了有效的 Actor PID
      if (!this.pid) {
        if (!this.cluster.getAsync) {
          throw new Error('Cluster 实例没有 getAsync 方法');
        }
        
        const pid = await this.cluster.getAsync(this.kind, this.identity);
        if (!pid) {
          throw new Error(`无法激活 TestGrain: ${this.kind}/${this.identity}`);
        }
        
        this.pid = pid;
      }
      
      // 发送消息并等待响应
      const response = await this.requestToActor<{ state: string; pings: number; nodeId: string }>({ type: 'get-state' });
      return response;
    } catch (error) {
      console.error(`[TestGrain] GetState 失败:`, error);
      throw error;
    }
  }
  
  async updateState(value: string): Promise<{ success: boolean; state: string; nodeId: string }> {
    try {
      // 确保调用前已经获取了有效的 Actor PID
      if (!this.pid) {
        if (!this.cluster.getAsync) {
          throw new Error('Cluster 实例没有 getAsync 方法');
        }
        
        const pid = await this.cluster.getAsync(this.kind, this.identity);
        if (!pid) {
          throw new Error(`无法激活 TestGrain: ${this.kind}/${this.identity}`);
        }
        
        this.pid = pid;
      }
      
      // 发送消息并等待响应
      const response = await this.requestToActor<{ success: boolean; state: string; nodeId: string }>({ 
        type: 'update-state', 
        value 
      });
      return response;
    } catch (error) {
      console.error(`[TestGrain] UpdateState 失败:`, error);
      throw error;
    }
  }

  /**
   * 向 Actor 发送请求并等待响应
   * @param message 要发送的消息
   * @param timeout 超时时间（毫秒）
   * @returns 响应结果
   */
  private async requestToActor<T>(message: any, timeout: number = 5000): Promise<T> {
    const maxRetries = 3;
    let lastError: Error | null = null;
    
    for (let attempt = 0; attempt < maxRetries; attempt++) {
      try {
        // 获取有效的 Actor PID
        const pid = await this.getOrActivateActor();
        console.log(`[TestGrain] 尝试 #${attempt + 1} - 发送消息到: ${pid.toString()}`, message);
        console.log(`[TestGrain] PID详细信息: 地址=${pid.address}, ID=${pid.id}`);
        
        // 获取 Actor 系统并发送请求
        const actorSystem = this.cluster.getActorSystem();
        
        // 获取集群提供者
        const provider = this.cluster.getProvider() as Libp2pProvider;
        
        // 检查目标地址是否是当前节点
        const isLocalNode = pid.address === this.cluster.getConfig().nodeAddress;
        console.log(`[TestGrain] 是否为本地节点: ${isLocalNode}`);
        
        if (isLocalNode) {
          // 本地节点，直接使用 PID 发送
          console.log(`[TestGrain] 使用本地发送机制发送消息`);
          
          // 检查 PID 是否有效
          const registry = ProcessRegistry.getInstance();
          const actorExists = registry.get(pid);
          
          if (!actorExists) {
            console.log(`[TestGrain] 警告: PID ${pid.toString()} 在本地找不到，尝试重新激活`);
            // 清除当前 PID，下次循环会重新激活
            this.pid = null;
            continue;
          }
          
          // 发送请求并等待响应
          console.log(`[TestGrain] 创建请求 Future，超时: ${timeout}ms`);
          const future = actorSystem.root.requestFuture(pid, message, timeout);
          
          console.log(`[TestGrain] 等待响应...`);
          const result = await future.toPromise();
          console.log(`[TestGrain] 收到响应:`, result);
          
          if (result === null || result === undefined) {
            throw new Error('收到空响应');
          }
          
          return result as T;
        } else {
          // 远程节点，使用 libp2p 发送
          console.log(`[TestGrain] 使用 libp2p 发送跨节点消息`);
          
          if (!provider.sendDirectMessage) {
            console.error(`[TestGrain] Provider 缺少 sendDirectMessage 方法`);
            throw new Error('Provider 不支持直接消息发送');
          }
          
          // 创建唯一的 Future ID
          const futureId = `future$${Date.now()}-${Math.floor(Math.random() * 1000000)}`;
          
          // 创建一个 Promise 用于接收响应
          const responsePromise = new Promise<T>((resolve, reject) => {
            // 创建超时处理
            const timeoutId = setTimeout(() => {
              console.log(`[TestGrain] 请求超时: ${futureId}`);
              reject(new Error(`请求超时，超时时间: ${timeout}ms`));
              
              // 清除响应处理器
              provider.removeResponseHandler(futureId);
            }, timeout);
            
            // 设置响应处理器
            provider.setResponseHandler(futureId, (response: any) => {
              clearTimeout(timeoutId);
              console.log(`[TestGrain] libp2p 收到响应:`, response);
              resolve(response as T);
            });
          });
          
          // 准备消息对象
          const requestMessage = {
            type: 'actor-request',
            actorId: pid.id,
            message: message,
            requestId: futureId,
            senderAddress: this.cluster.getConfig().nodeAddress
          };
          
          // 发送消息到对应节点
          console.log(`[TestGrain] 通过 libp2p 发送消息到: ${pid.address}`);
          await provider.sendDirectMessage(pid.address, requestMessage);
          
          // 等待响应
          return await responsePromise;
        }
      } catch (error) {
        lastError = error as Error;
        console.error(`[TestGrain] 请求失败 (尝试 #${attempt + 1}):`, error);
        
        // 如果是最后一次尝试，抛出错误
        if (attempt === maxRetries - 1) {
          throw new Error(`请求失败 (${maxRetries} 次尝试后): ${lastError.message}`);
        }
        
        // 等待一段时间后重试
        const retryDelay = Math.min(1000 * Math.pow(2, attempt), 5000); // 指数退避，最大5秒
        console.log(`[TestGrain] 等待 ${retryDelay}ms 后重试...`);
        await new Promise(resolve => setTimeout(resolve, retryDelay));
      }
    }
    
    // 这里实际上不会执行到，因为最后一次失败会在循环中抛出错误
    throw lastError || new Error('未知错误');
  }
}

// ====== 测试Grain工厂 ======

class TestGrainFactory {
  constructor(private cluster: Cluster) {}
  
  get(grainId: string): TestGrain {
    return new TestGrain(this.cluster, grainId);
  }
}

// ====== 节点类 ======

class ClusterNode {
  private system: ActorSystem;
  private remote!: Remote;
  private cluster!: Cluster;
  private clusterRouter!: ClusterRouter;
  private grainFactory: TestGrainFactory;
  
  constructor(
    private nodeId: string,
    private port: number,
    private bootstrapAddrs?: string[]
  ) {
    console.log(`创建集群节点: ${nodeId}, 端口: ${port}`);
    
    // 创建 Actor 系统
    this.system = new ActorSystem();
    
    // 初始化 Grain 工厂 - 由于 cluster 尚未创建，需要在 start 中重新设置
    this.grainFactory = new TestGrainFactory(null as any);
  }
  
  async start(): Promise<void> {
    try {
      // 初始化本地地址
      const localAddress = `localhost:${this.port}`;
      
      // 设置进程注册表地址
      const registry = ProcessRegistry.getInstance();
      if (registry._setAddress) {
        registry._setAddress(localAddress);
        console.log(`[${this.nodeId}] 进程注册表地址已设置为: ${localAddress}`);
      }
      
      // 1. 启动远程系统
      this.remote = new Remote(this.system);
      await this.remote.start('localhost', this.port);
      console.log(`[${this.nodeId}] 远程系统已启动`);
      
      // 2. 创建 Cluster 实例
      this.cluster = this.createCluster();
      
      // 3. 初始化集群
      await this.cluster.init();
      console.log(`[${this.nodeId}] 集群已初始化`);
      
      // 4. 创建路由器
      this.clusterRouter = new ClusterRouter(this.system, this.cluster);
      
      // 5. 设置 router 到 cluster
      this.cluster.setRouter(this.clusterRouter);
      
      // 6. 更新 Grain 工厂
      this.grainFactory = new TestGrainFactory(this.cluster);
      
      // 7. 注册 Grain 类型
      this.registerGrain();
      
      // 8. 启动集群
      await this.cluster.start();
      console.log(`[${this.nodeId}] 集群已启动`);
      
      // 8. 输出当前注册信息
      if (registry.getAllProcesses) {
        console.log(`[${this.nodeId}] 当前进程注册表状态:`, registry.getAllProcesses());
      } else {
        console.log(`[${this.nodeId}] 无法获取进程注册表状态，getAllProcesses方法不可用`);
      }
    } catch (error) {
      console.error(`[${this.nodeId}] 启动失败:`, error);
      throw error;
    }
  }
  
  private createCluster(): Cluster {
    const clusterConfig: ClusterConfig = {
      clusterName: 'p2p-test-cluster',
      nodeAddress: `localhost:${this.port}`,
      hostname: 'localhost',
      port: this.port,
      providerType: 'libp2p',
      providerConfig: {},
      reconnectInterval: 1000,
      heartbeatInterval: 1000,
      enableVirtualNodes: false,
      virtualNodeCount: 10
    };
    
    // 创建 libp2p 集群提供者
    const provider = new Libp2pProvider({
      listenAddrs: [`/ip4/127.0.0.1/tcp/0`],
      bootstrapAddrs: this.bootstrapAddrs,
      enableMDNS: true,
      enableDHT: true,
      enableGossip: true,
      heartbeatInterval: 1000,
      memberTTL: 10000,
      leaderElectionInterval: 5000
    });
    
    // 创建本地身份查找
    const identityLookup = new LocalIdentityLookup({
      enableCache: true,
      defaultLookupTimeout: 5000,
      cacheExpiration: 60000
    });
    
    // 创建集群
    return new Cluster(
      this.system,
      this.remote,
      clusterConfig,
      provider,
      identityLookup
    );
  }
  
  private registerGrain() {
    // 注册Grain - 移动到集群启动之前
    console.log(`[${this.nodeId}] 注册Grain类型: test`);
    const registry = GrainRegistry.getInstance();
    
    // 修改Grain注册方式，使用正确的ID格式
    registry.registerGrain('test', (identity: string) => {
      console.log(`[${this.nodeId}] 创建TestActor实例，identity=${identity}`);
      
      // 使用ClusterIdentity来生成正确的Actor ID
      const clusterIdentity = new ClusterIdentity('test', identity);
      const actorId = clusterIdentity.getActorId();
      console.log(`[${this.nodeId}] ActorID将是: ${actorId}`);
      
      return Props.fromProducer(() => {
        console.log(`[${this.nodeId}] 实例化TestActor: ${actorId}`);
        return new TestActor(this.nodeId);
      });
    });
    
    // 监听集群事件 - 使用枚举而非字符串
    this.cluster.on(ClusterEventType.MemberJoined, (event: ClusterEvent) => {
      console.log(`[${this.nodeId}] 成员加入: ${event.member?.id}`);
    });
    
    this.cluster.on(ClusterEventType.MemberLeft, (event: ClusterEvent) => {
      console.log(`[${this.nodeId}] 成员离开: ${event.member?.id}`);
    });
    
    this.cluster.on(ClusterEventType.LeaderElected, (event: ClusterEvent) => {
      console.log(`[${this.nodeId}] 新领导者: ${event.leaderId}`);
    });
  }
  
  async stop(): Promise<void> {
    await this.cluster.shutdown();
    await this.remote.shutdown();
    console.log(`[${this.nodeId}] 节点已关闭`);
  }
  
  getGrainFactory(): TestGrainFactory {
    return this.grainFactory;
  }
  
  async getClusterInfo(): Promise<any> {
    const members = await this.cluster.getMembers();
    const leader = await this.cluster.getLeader();
    const isLeader = await this.cluster.isLeader();
    const metadata = await this.cluster.getProvider().getClusterMetadata();
    
    return {
      nodeId: this.nodeId,
      members: members.map(m => ({
        id: m.id,
        status: m.status,
        address: m.address
      })),
      leader: leader?.id,
      isLeader,
      metadata
    };
  }
}

// ====== 主测试函数 ======

async function runTest() {
  try {
    console.log('开始P2P集群验证...');
    
    // 创建3个节点，使用mDNS自动发现而不是硬编码地址
    const node1 = new ClusterNode('node1', 12001);
    const node2 = new ClusterNode('node2', 12002);
    const node3 = new ClusterNode('node3', 12003);
    
    // 启动所有节点
    console.log('\n1. 启动节点...');
    await node1.start();
    await delay(1000);
    await node2.start();
    await delay(1000);
    await node3.start();
    
    // 等待集群稳定
    console.log('\n2. 等待集群稳定...');
    await delay(5000);
    
    // 验证集群状态
    console.log('\n3. 验证集群状态...');
    const info1 = await node1.getClusterInfo();
    const info2 = await node2.getClusterInfo();
    const info3 = await node3.getClusterInfo();
    
    console.log('Node1 信息:', JSON.stringify(info1, null, 2));
    console.log('Node2 信息:', JSON.stringify(info2, null, 2));
    console.log('Node3 信息:', JSON.stringify(info3, null, 2));
    
    // 测试Grain通信
    console.log('\n4. 测试Grain通信...');
    const factory1 = node1.getGrainFactory();
    const factory2 = node2.getGrainFactory();
    const factory3 = node3.getGrainFactory();
    
    const grain1 = factory1.get('test1');
    const grain2 = factory2.get('test1'); // 同一个Grain的不同引用
    const grain3 = factory3.get('test2'); // 不同的Grain
    
    // 测试ping
    console.log('\n4.1 测试ping...');
    const ping1 = await grain1.ping();
    const ping2 = await grain2.ping();
    const ping3 = await grain3.ping();
    
    console.log('Grain1 ping:', ping1);
    console.log('Grain2 ping (same as Grain1):', ping2);
    console.log('Grain3 ping:', ping3);
    
    // 测试状态更新
    console.log('\n4.2 测试状态更新...');
    await grain1.updateState('Updated by node1');
    const state1 = await grain1.getState();
    const state2 = await grain2.getState();
    
    console.log('Grain1 state:', state1);
    console.log('Grain2 state (same as Grain1):', state2);
    
    // 测试故障转移
    console.log('\n5. 测试故障转移...');
    console.log('关闭node1...');
    await node1.stop();
    
    // 等待集群重新稳定
    await delay(5000);
    
    // 验证其他节点仍然可用
    console.log('\n5.1 验证剩余节点状态...');
    const info2After = await node2.getClusterInfo();
    const info3After = await node3.getClusterInfo();
    
    console.log('Node2 信息:', JSON.stringify(info2After, null, 2));
    console.log('Node3 信息:', JSON.stringify(info3After, null, 2));
    
    // 验证可以通过其他节点访问Grain
    console.log('\n5.2 验证Grain可用性...');
    const stateAfterFailure = await grain2.getState();
    console.log('通过node2访问Grain1:', stateAfterFailure);
    
    // 清理
    console.log('\n6. 清理...');
    await node2.stop();
    await node3.stop();
    
    console.log('\nP2P集群验证完成');
  } catch (error) {
    console.error('测试失败:', error);
  }
}

// 运行测试
runTest().catch(console.error); 